package com.poetry.service.impl;

import java.time.LocalDateTime;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.poetry.exception.ResourceNotFoundException;
import com.poetry.model.Category;
import com.poetry.model.Poem;
import com.poetry.model.User;
import com.poetry.model.dto.PoemDTO;
import com.poetry.repository.CategoryRepository;
import com.poetry.repository.PoemRepository;
import com.poetry.repository.UserRepository;
import com.poetry.service.PoemService;

@Service
public class PoemServiceImpl implements PoemService {

    private static final int PAGE_SIZE = 10;
    
    @Autowired
    private PoemRepository poemRepository;
    
    @Autowired
    private UserRepository userRepository;
    
    @Autowired
    private CategoryRepository categoryRepository;

    @Override
    public List<Poem> findAll() {
        return poemRepository.findAll();
    }
    
    @Override
    public Page<Poem> findAll(int page, String keyword, Long categoryId, String sort) {
        Sort sorting = Sort.by(Sort.Direction.DESC, "createdAt");
        if ("popular".equals(sort)) {
            sorting = Sort.by(Sort.Direction.DESC, "likeCount");
        } else if ("commented".equals(sort)) {
            sorting = Sort.by(Sort.Direction.DESC, "commentCount");
        }
        
        PageRequest pageRequest = PageRequest.of(page, PAGE_SIZE, sorting);
        
        if (keyword != null && !keyword.isEmpty()) {
            return poemRepository.findByTitleContainingOrContentContaining(keyword, keyword, pageRequest);
        }
        
        if (categoryId != null) {
            return poemRepository.findByCategory_Id(categoryId, pageRequest);
        }
        
        return poemRepository.findAll(pageRequest);
    }
    
    @Override
    public Page<Poem> findByCategory(Long categoryId, int page) {
        Category category = categoryRepository.findById(categoryId)
            .orElseThrow(() -> new ResourceNotFoundException("Category not found with id: " + categoryId));
            
        return poemRepository.findByCategory_Id(categoryId, 
            PageRequest.of(page, PAGE_SIZE, Sort.by(Sort.Direction.DESC, "createdAt")));
    }
    
    @Override
    public List<Poem> findLatestPoems() {
        return poemRepository.findAll(
            PageRequest.of(0, 5, Sort.by(Sort.Direction.DESC, "createdAt"))
        ).getContent();
    }
    
    @Override
    public List<Poem> findPopularPoems() {
        return poemRepository.findAll(
            PageRequest.of(0, 5, Sort.by(Sort.Direction.DESC, "likeCount"))
        ).getContent();
    }

    @Override
    public Poem findById(Long id) {
        return poemRepository.findById(id)
            .orElseThrow(() -> new ResourceNotFoundException("Poem not found with id: " + id));
    }

    @Override
    @Transactional
    public Poem create(PoemDTO poemDTO) {
        User author = userRepository.findById(poemDTO.getAuthorId())
            .orElseThrow(() -> new ResourceNotFoundException("User not found with id: " + poemDTO.getAuthorId()));
            
        Category category = null;
        if (poemDTO.getCategoryId() != null) {
            category = categoryRepository.findById(poemDTO.getCategoryId())
                .orElseThrow(() -> new ResourceNotFoundException("Category not found with id: " + poemDTO.getCategoryId()));
        }
            
        Poem poem = new Poem();
        poem.setTitle(poemDTO.getTitle());
        poem.setContent(poemDTO.getContent());
        poem.setAuthor(author);
        poem.setCategory(category);
        poem.setCreatedAt(LocalDateTime.now());
        poem.setUpdatedAt(LocalDateTime.now());
        return poemRepository.save(poem);
    }

    @Override
    @Transactional
    public Poem update(Long id, PoemDTO poemDTO) {
        Poem poem = findById(id);
        poem.setTitle(poemDTO.getTitle());
        poem.setContent(poemDTO.getContent());
        
        if (poemDTO.getCategoryId() != null) {
            Category category = categoryRepository.findById(poemDTO.getCategoryId())
                .orElseThrow(() -> new ResourceNotFoundException("Category not found with id: " + poemDTO.getCategoryId()));
            poem.setCategory(category);
        }
        
        poem.setUpdatedAt(LocalDateTime.now());
        return poemRepository.save(poem);
    }

    @Override
    @Transactional
    public void delete(Long id) {
        if (!poemRepository.existsById(id)) {
            throw new ResourceNotFoundException("Poem not found with id: " + id);
        }
        poemRepository.deleteById(id);
    }
} 